package com.jieshao.rule

import com.intellij.icons.AllIcons
import com.jieshao.utils.LineShareBundle.message
import javax.swing.Icon

sealed class Rule(
    //https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/-regex/
    //https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html
    var originMatch: Regex,
    var name: String,
    var icon: Icon?,
    var template: String = "\"\${convertGitUrl2Https(origin)}/blob/\$currentRevision\${filePath}#L\${(\"\${lineSelection?.first}\" + if (null != lineSelection?.second && lineSelection?.first!=lineSelection?.second) \"-L\${lineSelection?.second}\" else \"\")}\""
) {

    val id: Int = getNextId()

    companion object {
        private var nextId = 0
        fun getNextId(): Int {
            return nextId++
        }
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as Rule

        return id == other.id
    }

    override fun hashCode(): Int {
        return id.hashCode()
    }
}

class GitHub : Rule(
    "^(?:git@|https://)github\\.com.*".toRegex(),
    message("rule.github.name"),
    AllIcons.Vcs.Vendors.Github
)

class Gitee : Rule(
    "^(?:git@|https://)gitee\\.com.*".toRegex(),
    message("rule.gitee.name"),
    null
)

class GitLab : Rule(
    "^(?:git@|https://)gitlab\\.com.*".toRegex(),
    message("rule.gitlab.name"),
    null
)

class BitbucketCloud : Rule(
    "^(?:git@|https://)bitbucket\\.org.*".toRegex(),
    message("rule.bitbucket.cloud.name"),
    null,
    "\"\${convertGitUrl2Https(origin)}/src/\$currentRevision\${filePath}#lines-\${(\"\${lineSelection?.first}\" + if (null != lineSelection?.second && lineSelection?.first!=lineSelection?.second) \":\${lineSelection?.second}\" else \"\")}\""
)

class BitbucketServer : Rule(
    "(?i).*bitbucket.*".toRegex(),
    message("rule.bitbucket.server.name"),
    null,
    """
        val (host,project,repository) = "(https://[.\\w]+)/(?:scm/)?([-\\w]+)/([-\\w]+)".toRegex().matchEntire(convertGitUrl2Https(origin))!!.destructured
        var line = lineSelection?.let{
            "L"+it.first+(if (it.second!=it.first) "-${'$'}{it.second}" else "")
        }?:""
        "${'$'}host/projects/${'$'}project/repos/${'$'}repository/browse/${'$'}{filePath.removePrefix("/")}?at=${'$'}currentRevision#${'$'}line"
    """.trimIndent()
)

class Gogs : Rule(
    "^(?:git@|https://)gogs\\.io.*".toRegex(),
    message("rule.gogs.name"),
    null
)

class Srht : Rule(
    "^(?:git@|https://)git\\.sr\\.ht.*".toRegex(),
    message("rule.srht.name"),
    null
)

class Gitea : Rule(
    "^(?:git@|https://)gitea\\.io.*".toRegex(),
    message("rule.gitea.name"),
    null
)

class Azure : Rule(
    "(?i).*azure.*".toRegex(),
    message("rule.azure.name"),
    null,
    """
        import java.net.URI
        import java.net.URLEncoder
        import java.nio.charset.Charset
        
        val params = mapOf(
            "version" to "GC".plus(currentRevision),
            "path" to filePath.removePrefix("/"),
        ) + (lineSelection?.let {
            mapOf(
                "line" to it.first.toString(),
                "lineEnd" to it.second.toString(),
                "lineStartColumn" to "1",
                "lineEndColumn" to "1"
            )
        }?: emptyMap())
        
        
        var https = URI.create(convertGitUrl2Https(origin))
        var basePathParts = https.path
            .removePrefix("v3/")
            .split("/")
            .toMutableList()
        
        if (!basePathParts.contains("_git")) {
            // urls might have an option company component, if that's the case we need to insert _git in between company/project and repository parts
            val indexToAddGit = if (basePathParts.size >= 3) 2 else 1
            basePathParts.add(indexToAddGit, "_git")
        }
        
        https = https.resolve(basePathParts.joinToString("/")+'?'+params.entries.joinToString("&") { (key, value) ->
            "${'$'}{URLEncoder.encode(key, Charset.defaultCharset())}=${'$'}{URLEncoder.encode(value, Charset.defaultCharset())}"
        })
        
        if (https.host.startsWith("ssh.")) {
            https = URI(https.scheme, https.host.removePrefix("ssh."),https.path,null)
        }
        
        https.toString()
    """.trimIndent()
)


class Chromium : Rule(
    "^(?:git@|https://)googlesource\\.com.*".toRegex(),
    message("rule.chromium.name"),
    null
)

class Gerrit : Rule(
    ".*gerrit.*".toRegex(RegexOption.IGNORE_CASE),
    message("rule.gerrit.name"),
    null
)

class CustomRule(ruleName: String): Rule(
    "^".toRegex(),
    ruleName,
    null
)
